/**
*    Copyright (C) 2008  Chase Kernan 
*    chase.kernan@gmail.com
*
*    This program is free software: you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation, either version 3 of the License, or
*    (at your option) any later version.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.
*
*    You should have received a copy of the GNU General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
* 
**/

package com.chasekernan.hxnova.core.battles;

import com.chasekernan.hxnova.core.players.PlayerRelations;
import com.chasekernan.hxnova.utils.XmlBuilder;
import com.chasekernan.hxnova.core.designs.HullDesign;

/**
    Ships will attack those ships whose owners are specified as battle opponents
    by their battle plans.
**/
enum BattleOpponents {
    Everyone;
    NuetralsAndEnemies;
    Enemies;
}

enum BattleTarget {
    None;
    Any;
    Starbase;
    ArmedShips;
    BombersAndFrieghters;
    UnarmedShips;
    FuelTransports;
    Frieghters;
}

enum BattleTactic {
    Disengage;
    DisengageIfChallenged;
    MinimizeDamageToSelf;
    MaximizeNetDamage;
    MaximizeDamageRatio;
    MaximizeDamage;
}

/**
    NOTE: VERY IMPORTANT: THIS IS DIFFERENT FROM "STARS!" AS BATTTLE PLANS ARE
    DISTRIBUTED BY SHIP DESIGN INSIDE A FLEET, NOT THE FLEET AS A WHOLE.
**/
class BattlePlan {
    
    public static var DEFAULT_TARGET = Any;
    public static var DEFAULT_OPPONENTS = NuetralsAndEnemies;
    public static var DEFAULT_DUMP_CARGO = false;
    public static var DEFAULT_TACTIC = MaximizeDamageRatio;
    
    public static var DEFAULT_BATTLE_PLAN = new BattlePlan("Default");
    public static var STARBASE_BATTLE_PLAN = new BattlePlan("$$$Starbase$$$");
        
    
    public var name : String;
    public var primaryTarget : BattleTarget;
    public var secondaryTarget : BattleTarget;
    public var opponents : BattleOpponents;
    public var dumpCargo : Bool;
    public var tactic : BattleTactic;
    
    /**
        Creates a new battle plan with the default targets, opponents, tactic 
        and dump cargo options. The name of the battle plan must be specified.
    **/
    public function new(name : String) {
        this.name = name;
        
        primaryTarget = DEFAULT_TARGET;
        secondaryTarget = DEFAULT_TARGET;
        opponents = DEFAULT_OPPONENTS;
        tactic = DEFAULT_TACTIC;
        dumpCargo = DEFAULT_DUMP_CARGO;
    }
    
    /**
        Returns true if the relationship to a player falls under the category of
        a battle opponent with this battle plan.
    **/
    public function isBattleOpponent(relation : Relation) : Bool {
        return switch(opponents) {
            case Everyone: true;
            
            case NuetralsAndEnemies:
                switch(relation) {
                    case Friend: false;
                    default: true;
                }
                
            case Enemies:
                switch(relation) {
                    case Enemy: true;
                    default: false;
                }
        };
    }
    
    /**
        Returns true if the given design would be targetted by this battle plan
        as a primary target.
    **/
    public function isPrimaryTarget(design : HullDesign) : Bool {
        return isTarget(design, primaryTarget);
    }
    
    /**
        Returns true if the given design would be targetted by this battle plan
        as a secondary target.
    **/
    public function isSecondaryTarget(design : HullDesign) : Bool {
        return isTarget(design, secondaryTarget);
    }
    
    private function isTarget(design : HullDesign, target : BattleTarget) 
            : Bool {
        return switch(target) {
            case None: false;
            
            case Any: true;
            
            case Starbase: design.isStarbase();
            
            case ArmedShips: design.hasWeapons();
            
            case BombersAndFrieghters: 
                design.hasBombingCapabilities() || 
                design.getCargoCapacity() > 0;
                
            case UnarmedShips: !design.hasWeapons();
            
            case FuelTransports: 
                design.getFuelCapacity() > design.baseHull.fuelCapacity; //||
                //TODO: Hulls that are specifically designed to carry fuel need
                //to be targeted here.
                
            case Frieghters:
                design.getCargoCapacity() > 0;
        };
    }
    
    public function clone() : BattlePlan {
        var bp = new BattlePlan(name);
        bp.primaryTarget = primaryTarget;
        bp.secondaryTarget = secondaryTarget;
        bp.tactic = tactic;
        bp.opponents = opponents;
        bp.dumpCargo = dumpCargo;
        
        return bp;
    }
    
    public static var XML_TITLE = "battle_plan";
    
    /**
        Writes a battle plan to xml.
        Sample xml: 
            <battle_plan name="kill the innocents">
                <primary_target>UnarmedShips</primary_target>
                <secondary_target>Any</secondary_target>
                <opponents>Everyone</opponents>
                <tactic>MaximizeDamage</tactic>
                <dump_cargo>false<dump_cargo>
            </battle_plan>
    **/
    public static function writeToXml(bp : BattlePlan) : Xml {
        var xb = new XmlBuilder(XML_TITLE);
        
        xb.addAttributes(bp, ["name"]);
        
        xb.addValueChild("primary_target", bp.primaryTarget);
        xb.addValueChild("secondary_target", bp.secondaryTarget);
        xb.addValueChild("opponents", bp.opponents);
        xb.addValueChild("tactic", bp.tactic);
        xb.addValueChild("dump_cargo", bp.dumpCargo);
        
        return xb.xml;
    }
    
    public static function readFromXml(xml : Xml) : BattlePlan {
        var xb = XmlBuilder.fromXml(xml);
        
        var bp = new BattlePlan(xb.readStringAttribute("name"));
        
        bp.primaryTarget = Type.createEnum(BattleTarget, 
                xb.readValueChild("primary_target"));
                
        bp.secondaryTarget = Type.createEnum(BattleTarget, 
                xb.readValueChild("secondary_target"));
                
        bp.opponents = Type.createEnum(BattleOpponents, 
                xb.readValueChild("opponents"));
                
        bp.tactic = Type.createEnum(BattleTactic, xb.readValueChild("tactic"));
        
        bp.dumpCargo = xb.readValueChild("dump_cargo") == "true";
        
        return bp;
    }
}
